﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DynamicQueryLib;
using LinqKit;
using System.Data.Objects.SqlClient;
using System.Data;
namespace AuditModel
{
    public class ArchiveBL:IArchiveBL
    {
        #region IArchiveBL Members
        private AuditDBEntities db;

        public ArchiveBL()
        {
            db = new AuditDBEntities(); 
        }

        /// <summary>
        /// All the parameters are optional. For the string params, use ""; for the int, use 0.
        /// </summary>
        /// <param name="annualEventID"></param>
        /// <param name="archiveID"></param>
        /// <param name="subjectID"></param>
        /// <param name="countyCode"></param>
        /// <returns></returns>
        public IEnumerable<Archive> GetArchives(string annualEventID, string archiveID, 
            int subjectID, string countyCode)
        {
            List<Filter> filterList = new List<Filter>();
            if (annualEventID.Trim() != "")
            {
                Filter f = new Filter();
                f.Connector = FilterConnectorType.AND;
                f.PropertyName = "AnnualEventID";
                f.PropertyType=typeof(string);
                f.Values.Add(annualEventID);
                f.Operator = RelationalOperators.Contains;
                filterList.Add(f);
            }
            if (archiveID.Trim() != "")
            {
                Filter f = new Filter();
                f.Connector = FilterConnectorType.AND;
                f.PropertyName = "ID";
                f.PropertyType = typeof(string);
                f.Values.Add(archiveID);
                f.Operator = RelationalOperators.Contains;
                filterList.Add(f);
            }
            if (subjectID > 0)
            {
                Filter f = new Filter();
                f.Connector = FilterConnectorType.AND;
                f.PropertyName = "SubjectID";
                f.PropertyType = typeof(int);
                f.Values.Add(subjectID.ToString());
                f.Operator = RelationalOperators.Equals;
                filterList.Add(f);
            }
            if (countyCode.Trim() != "")
            {
                Filter f = new Filter();
                f.Connector = FilterConnectorType.AND;
                f.PropertyName = "CountyCode";
                f.PropertyType = typeof(string);
                f.Values.Add(countyCode);
                f.Operator = RelationalOperators.Contains;
                filterList.Add(f);
            }

            //var predicate = PredicateBuilder.True<Archive>();
            //foreach (var f in filterList)
            //{
            //    if (f != null)
            //    {
                    
            //        if (f.Connector == FilterConnectorType.AND)
            //        {

            //            //predicate = predicate.And(LambdaExpressionHelper<Archive>.ExpressionBuilder<int>  (f));//.ExpressionBuilder<int>(f));
            //            //predicate = predicate.And<Archive>(f);
            //            predicate = predicate.And(LambdaExpressionHelper<Archive>.ExpressionBuilder(f));
            //        }
            //        else
            //        {
            //            predicate = predicate.Or(LambdaExpressionHelper<Archive>.ExpressionBuilder(f));
            //        }
            //    }
            //}

            var predicate = LambdaExpressionHelper<Archive>.CreatePredicate<Archive>(filterList);

            return db.Archives.AsExpandable().Where(predicate).ToList();
        }

        private delegate int findYearHandler(string annualEventID);
        public void Add(Archive archive)
        {
            //Check ACL, make sure archive's subject exists in the ACL.
            bool isSubjectExists = true;
            IEnumerable<int> qSubjects = (from q in db.CandidateQuotas
                                          where q.AnnualEventID == archive.AnnualEventID
                                          && q.SubjectID == archive.SubjectID
                                          select q.SubjectID).ToList();
            if (qSubjects.Count() > 0)
            {
                isSubjectExists = true;
            }
            else
            {
                isSubjectExists = false;
            }
            if (isSubjectExists==false)
            {
                throw new Exception(string.Format("SubjectID {0} doesn't exist in the quota table.",archive.SubjectID));
            }


            //Check ACL, if exceeds quota
            //int quota = (int)(from q in db.CandidateQuotas
            //             where q.AnnualEventID == archive.AnnualEventID
            //             && q.SubjectID == archive.SubjectID
            //             && q.CountyCode == archive.CountyCode
            //             select q.Quota).Single();
            bool isQuotaExceeded;
            IEnumerable<bool> qList= (from q in db.sp_GetCandidateQuotas()
                                    where q.AnnualEventID == archive.AnnualEventID
                                    && q.SubjectID == archive.SubjectID
                                    && q.CountyCode == archive.CountyCode
                                    select q.Total >= q.Quota).ToList();
            if (qList.Count() == 0)
            {
                isQuotaExceeded = false;
            }
            else
            {
                isQuotaExceeded = qList.Single();
            }
            if (isQuotaExceeded) { throw new Exception("CandidateQuotaExceeded!"); }
            else//Add the archive
            {
                //Get the biggest number.
                int lastNum=0;
                var nums= (from t in db.Archives
                               select new {Count=t.ID.Substring(6)}).ToList();
                if (nums.Count == 0)
                {
                    lastNum = 1;
                }
                else
                {
                    lastNum = nums.Select(x => Convert.ToInt32(x.Count)).Max();
                }
                //Get year.
                findYearHandler findYear = (a_id) =>
                {
                    int r = (int)(from t in db.AnnualEvents
                                  where t.ID == a_id
                                  select t.Year).Single();
                    if (r <= 0) { throw new Exception("Cannot find Year by AnnualEventID#" + a_id); }
                    return r;
                };
                //Assemble the Archive ID. A sample ArchiveID is "PD201202"
                archive.ID = archive.CountyCode + findYear(archive.AnnualEventID).ToString() + (lastNum + 1).ToString();
                //Add new Archive to Database.
                db.Archives.AddObject(archive);
                db.SaveChanges();
            }
        }
        public void Update(Archive archive)
        {
            db.Archives.Attach(archive);
            db.ObjectStateManager.ChangeObjectState(archive, EntityState.Modified);
            db.SaveChanges();

            
        }
        #endregion
    }
}
